package com.sicong.admin.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sicong.admin.entity.User;
import com.sicong.admin.entity.UserRole;
import com.sicong.admin.dto.UserInfo;
import com.sicong.admin.service.UserRoleService;
import com.sicong.admin.service.UserService;
import com.sicong.common.annotation.Log;
import com.sicong.common.core.enums.ResultEnum;
import com.sicong.common.core.utils.Result;
import com.sicong.common.core.utils.ResultUtil;
import com.sicong.common.enums.LogModuleEnum;
import com.sicong.common.security.annotation.Inner;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author chenww
 * @since 2020-11-25
 */
@Log(module = LogModuleEnum.USER)
@Api(tags = {"用户控制器"})
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private UserRoleService userRoleService;

    @ApiOperation("添加用户")
    @PostMapping("/save")
    public Result<Void> saveUser(@ApiParam("用户名") @RequestParam("username") String username,
                                 @ApiParam("密码") @RequestParam("password") String password,
                                 @ApiParam("昵称") @RequestParam(value = "nickName", required = false) String nickName) {
        User user = new User()
                .setUsername(username)
                .setPassword(new BCryptPasswordEncoder().encode(password))
                .setNickName(nickName);
        userService.save(user);
        return ResultUtil.success();
    }

    @ApiOperation("删除用户")
    @DeleteMapping("/{userIds}")
    public Result<Void> removeUsers(@ApiParam("用户id") @PathVariable String userIds) {
        userService.removeByIds(Arrays.asList(userIds.split(",")));
        return ResultUtil.success();
    }

    @ApiOperation("修改用户信息")
    @PatchMapping("/{userId}")
    public Result<Void> updateUser(@ApiParam("用户id") @PathVariable Long userId,
                                   @ApiParam("旧密码") @RequestParam("password") String password,
                                   @ApiParam("新密码") @RequestParam("newPassword") String newPassword,
                                   @ApiParam("昵称") @RequestParam(value = "nickName", required = false) String nickName) {
        String oldPassword = userService.getOne(Wrappers.<User>lambdaQuery().select(User::getPassword).eq(User::getId, userId)).getPassword();
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        if (!bCryptPasswordEncoder.matches(password, oldPassword)) {
            return ResultUtil.error(ResultEnum.ERROR_PASSWORD);
        }
        User user = new User().setId(userId).setNickName(nickName)
                .setPassword(bCryptPasswordEncoder.encode(newPassword));
        userService.updateById(user);
        return ResultUtil.success();
    }

    @ApiOperation("分页查询用户")
    @GetMapping("/page")
    public Result<IPage<User>> getUsers(Page<User> page,
                                        @ApiParam("用户名") @RequestParam(value = "username", required = false) String username,
                                        @ApiParam("昵称") @RequestParam(value = "nickName", required = false) String nickName) {
        return ResultUtil.success(
                userService.page(page, Wrappers.<User>lambdaQuery()
                        .select(User::getId, User::getUsername, User::getNickName)
                        .eq(!StringUtils.isEmpty(username), User::getUsername, username)
                        .eq(!StringUtils.isEmpty(nickName), User::getNickName, nickName))
        );
    }

    @ApiOperation("添加角色")
    @PreAuthorize("hasAuthority('sys_user_add')")
    @PostMapping("/addRoles/{userId}")
    public Result<Void> addRoles(@ApiParam("用户id") @PathVariable Long userId,
                                 @ApiParam("角色id") @RequestParam("roleIds") String ids) {
        String[] roleIds = ids.split(",");
        List<UserRole> userRoles = new ArrayList<>();
        for (String roleId : roleIds) {
            userRoles.add(new UserRole().setUserId(userId).setRoleId(Long.valueOf(roleId)));
        }
        userRoleService.saveBatch(userRoles);
        return ResultUtil.success();
    }

    @ApiOperation("分配角色")
    @PatchMapping("/modifyRoles/{userId}")
    public Result<Void> modifyRoles(@ApiParam("用户id") @PathVariable Long userId,
                                    @ApiParam("角色id") @RequestParam("roleIds") String ids) {
        List<Long> newRoleIds = Arrays.stream(ids.split(","))
                .map(Long::valueOf).collect(Collectors.toList());
        userRoleService.remove(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getUserId, userId));
        List<UserRole> userRoles = new ArrayList<>();
        for (Long roleId : newRoleIds) {
            userRoles.add(new UserRole().setUserId(userId).setRoleId(roleId));
        }
        userRoleService.saveBatch(userRoles);
        return ResultUtil.success();
    }

    @Inner
    @ApiOperation("获取用户全部信息")
    @GetMapping("/info/{username}")
    public Result<UserInfo> info(@PathVariable String username) {
        User user = userService.getOne(Wrappers.<User>query().lambda().eq(User::getUsername, username));
        if (ObjectUtils.isEmpty(user)) {
            return ResultUtil.error(ResultEnum.ACCOUNT_NOT_EXIST.getCode(), String.format("用户信息为空 %s", username));
        }
        return ResultUtil.success(userService.findUserInfo(user));
    }

    @Inner
    @Log("查询用户信息")
    @GetMapping("/getUserByUsername/{username}")
    public Result<User> getUserByUsername(@PathVariable String username) {
        return ResultUtil.success(userService.getOne(Wrappers.<User>lambdaQuery()
                .select(User::getId, User::getUsername, User::getPassword, User::getNickName)
                .eq(User::getUsername, username)));
    }

}

